package org.pine.dictionary.service.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.read.listener.PageReadListener;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.baomidou.mybatisplus.core.metadata.IPage;
import jakarta.annotation.Resource;
import jakarta.servlet.http.HttpServletResponse;
import lombok.extern.slf4j.Slf4j;
import org.pine.dictionary.bean.PageRequest;
import org.pine.dictionary.bean.PageResponse;
import org.pine.dictionary.bean.excel.DictionaryImportDto;
import org.pine.dictionary.bean.request.DictionaryQueryRequest;
import org.pine.dictionary.bean.request.DictionarySaveRequest;
import org.pine.dictionary.bean.response.DictionaryQueryResponse;
import org.pine.dictionary.common.StatusEnum;
import org.pine.dictionary.service.IDictionaryService;
import org.pine.dictionary.service.bo.DictionaryBo;
import org.pine.dictionary.service.manager.DictionaryDetailManager;
import org.pine.dictionary.service.manager.DictionaryManager;
import org.pine.dictionary.util.PageUtil;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * <p>
 * 字典表 服务实现类
 * </p>
 *
 * @author pine
 * @since 2024-05-15
 */
@Slf4j
@Service
public class DictionaryServiceImpl implements IDictionaryService {

    @Resource
    private DictionaryManager dictionaryManager;

    @Resource
    private DictionaryDetailManager dictionaryDetailManager;

    /**
     * 新增字典
     *
     * @param request 请求
     */
    @Override
    public void insert(DictionarySaveRequest request) {
        // 请求体转换为业务对象
        DictionaryBo dictionaryBo = transformToEntity(request);
        // 生成字典ID
        dictionaryBo.setDictionaryId(IdUtil.getSnowflake().nextIdStr());
        // 校验插入数据
        checkForInsert(dictionaryBo);

        // 数据落库
        dictionaryManager.save(dictionaryBo);
    }

    /**
     * 按字典ID更新字典
     *
     * @param request 请求
     */
    @Override
    public void update(DictionarySaveRequest request) {
        // 查询原字典数据
        DictionaryBo oldDictionaryBo = dictionaryManager.getOne(request.getDictionaryId());
        if (Objects.isNull(oldDictionaryBo)) {
            return;
        }

        // 请求体转换为业务对象
        DictionaryBo dictionaryBo = transformToEntity(request);
        // 校验更新数据
        checkForUpdate(dictionaryBo);
        // 更新时不更新编码
        dictionaryBo.setCode(null);

        // 数据落库
        dictionaryManager.updateById(dictionaryBo);
    }

    /**
     * 删除字典
     *
     * @param idList id 列表
     */
    @Override
    public void delete(List<String> idList) {
        dictionaryManager.removeBatchByIds(idList);
    }

    /**
     * 按字典ID查字典信息
     *
     * @param id id
     * @return 响应
     */
    @Override
    public DictionaryQueryResponse getDetail(String id) {
        DictionaryBo entity = dictionaryManager.getOne(id);
        return transformToResponse(entity);
    }

    /**
     * 查询字典信息（分页）
     *
     * @param request 请求
     * @return PageResponse 响应
     */
    @Override
    public PageResponse<DictionaryQueryResponse> list(PageRequest<DictionaryQueryRequest> request) {

        // 分页查询字典信息
        IPage<DictionaryBo> dictionaryPage = dictionaryManager.page(transformToQuery(request));

        // 组装响应结果
        return PageUtil.convertPage(dictionaryPage, dictionaryPage.getRecords().stream().map(this::transformToResponse).collect(Collectors.toList()));
    }

    /**
     * 启用
     *
     * @param idList id 列表
     */
    @Override
    public void enable(List<String> idList) {
        dictionaryManager.changeStatus(idList, StatusEnum.ENABLE);
        dictionaryDetailManager.changeStatusByDictionaryIds(idList, StatusEnum.ENABLE);
    }

    /**
     * 禁用
     *
     * @param idList id 列表
     */
    @Override
    public void disable(List<String> idList) {
        dictionaryManager.changeStatus(idList, StatusEnum.DISABLE);
        dictionaryDetailManager.changeStatusByDictionaryIds(idList, StatusEnum.DISABLE);
    }

    /**
     * 导入字典
     *
     * @param file 表格文件
     */
    @Override
    public void importExcel(MultipartFile file) {
        try {
            EasyExcel.read(file.getInputStream(), DictionaryImportDto.class, new PageReadListener<DictionaryImportDto>(importDtos -> {
                // todo 数据校验

                // 数据转换
                List<DictionaryBo> dictionaryBos = transformToEntities(importDtos);

                for (DictionaryBo dictionaryBo : dictionaryBos) {
                    // 数据校验
                    checkForInsert(dictionaryBo);

                    // 设置字典ID
                    dictionaryBo.setDictionaryId(IdUtil.getSnowflake().nextIdStr());
                }

                // 保存到数据库
                int insertNums = dictionaryManager.saveBatch(dictionaryBos);
                log.info("插入数据条数：{}", insertNums);
            })).sheet().doRead();
        } catch (IOException e) {
            log.warn("上传文件异常 {}", e.getLocalizedMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 获取导入模版
     *
     * @param response servlet响应对象
     */
    @Override
    public void importTpl(HttpServletResponse response) {
        try {
            // 设置相应格式
            response.setContentType(MediaType.APPLICATION_OCTET_STREAM_VALUE);
            response.setCharacterEncoding("utf-8");

            // URLEncoder.encode 可以防止中文乱码
            String filename = "字典_导入模版_" + LocalDateTime.now();
            filename = URLEncoder.encode(filename, StandardCharsets.UTF_8).replaceAll("\\+", "%20");
            response.setHeader("Content-disposition", "attachment;filename*=" + filename + ".xlsx");
            try (ExcelWriter excelWriter = EasyExcel.write(response.getOutputStream(), DictionaryImportDto.class).autoCloseStream(false).build()) {
                WriteSheet writeSheet = EasyExcel.writerSheet("sheet").build();
                excelWriter.write(Collections.emptyList(), writeSheet);
            }
        } catch (Exception e) {
            log.warn("导出模版异常 {}", e.getLocalizedMessage(), e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 导出字典
     *
     * @param response servlet响应对象
     * @param request 请求参数
     */
    @Override
    public void export(HttpServletResponse response, DictionaryQueryRequest request) throws IOException {

    }
}
